package com.jy.rhin.infra.repo.notfication.subscribe;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.jy.common.UIDWorker;
import com.jy.rhin.domain.notification.subscribe.SubscribeDao;
import com.jy.rhin.domain.notification.subscribe.entity.EnumSubscribeStatus;
import com.jy.rhin.domain.notification.subscribe.entity.SubscribeDO;
import com.jy.rhin.domain.notification.subscribe.entity.vo.SubscribeTopicFilterVO;
import com.jy.rhin.infra.repo.notfication.subscribe.mapper.SubscribeMapper;
import com.jy.rhin.infra.repo.notfication.subscribe.mapper.SubscribeTopicFilterMapper;
import com.jy.rhin.infra.repo.notfication.subscribe.po.SubscribePO;
import com.jy.rhin.infra.repo.notfication.subscribe.po.SubscribeTopicFilterPO;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author WeiQ
 * @date 2022/6/28 14:03
 */
@Slf4j
@Component
public class SubscribeDaoImpl implements SubscribeDao {

    protected Log mpLog = LogFactory.getLog(getClass());
    @Resource
    SubscribeMapper subscribeMapper;
    @Resource
    UIDWorker uidWorker;

    @Resource
    SubscribeTopicFilterMapper subscribeTopicFilterMapper;

    @Override
    public SubscribeDO queryById(Long id) {
        SubscribePO po = subscribeMapper.selectById(id);
        return Objects.isNull(po) ? null : po.toDO();
    }

    /**
     * 根据订阅者+订阅主题查询可用的订阅记录
     *
     * @param subscriberCode
     * @param topicExp
     * @return
     */
    @Override
    public SubscribeDO queryBySubscriberAndTopic(String subscriberCode, String topicExp) {
        QueryWrapper<SubscribePO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .ne(SubscribePO::getStatus, EnumSubscribeStatus.CANCEL.name())
                .eq(SubscribePO::getSubscriberCode, subscriberCode)
                .eq(SubscribePO::getTopicExp, topicExp);
        SubscribePO po = subscribeMapper.selectOne(queryWrapper);
        return Objects.isNull(po) ? null : po.toDO();
    }

    /**
     * 保存订阅记录
     *
     * @param subscribeDO
     */
    @Override
    public void save(SubscribeDO subscribeDO) {
        SubscribePO po = new SubscribePO(subscribeDO);
        if (Objects.isNull(po.getId())) {
            //新增
            long id = uidWorker.nextId();
            po.setId(id);
            subscribeDO.setId(id);
            subscribeMapper.insert(po);
        } else {
            //更新
            subscribeMapper.updateById(po);
            //更新需要刷新子表数据，先清空子表关联的数据
            clearSubscribe(po.getId());
        }
        List<SubscribeTopicFilterVO> filterList = subscribeDO.getFilterList();
        List<SubscribeTopicFilterPO> filterPoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(filterList)) {
            //插入字表数据
            Long subscribeId = po.getId();
            filterList.forEach(filterVo -> {
                long filterId = uidWorker.nextId();
                SubscribeTopicFilterPO filterPo = new SubscribeTopicFilterPO(filterVo, filterId, subscribeId);
                filterPoList.add(filterPo);
            });
        }
        //批量插入子表数据
        SqlHelper.executeBatch(SubscribeTopicFilterPO.class, mpLog, filterPoList, 100, (sqlSession, entity) -> sqlSession.insert(SqlHelper.getSqlStatement(SubscribeTopicFilterMapper.class, SqlMethod.INSERT_ONE), entity));
    }

    /**
     * 更新订阅状态
     *
     * @param subscribe
     * @return
     */
    @Override
    public Boolean update(SubscribeDO subscribe) {
        subscribeMapper.updateById(new SubscribePO(subscribe));
        return Boolean.TRUE;
    }

    /**
     * 清空字表关联的数据
     *
     * @param subscribeId
     */
    private void clearSubscribe(Long subscribeId) {
        subscribeTopicFilterMapper.removeQueryFilter(subscribeId);
    }
}
